#include "stm8s.h"
#include "system.h"
#include "ril.h"
/*
uint8_t adcindoing;
FlagStatus adcstatus;
uint16_t adcv4ch;
uint16_t adcv3ch;
*/
void waitn(uint16_t nCount)
{
    /* Decrement nCount value */
    while (nCount != 0)
    {
        nCount--;
    }
}

void waits(uint16_t nCount)
{
    /* Decrement nCount value */
    while (nCount != 0)
    {
        nCount--;
        waitn(60000);
    }
}
#if 0
void adc_config(uint8_t mod)
{
    /* De-Init ADC peripheral*/
    ADC1_DeInit();

    /* Init ADC2 peripheral */
    ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_4, ADC1_PRESSEL_FCPU_D8, \
                ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL4,\
                DISABLE);
    if (1 == mod){
        ADC1_ScanModeCmd(ENABLE);
    }
    /* Enable EOC interrupt */
    //ADC1_ITConfig(ADC1_IT_EOCIE, ENABLE);
    adcindoing = !0;
    /*Start Conversion */
    ADC1_StartConversion();
}

void adc_monitor()
{
    if (adcindoing)
    {
        adcstatus = ADC1_GetFlagStatus(ADC1_FLAG_EOC);
        if(adcstatus){
            adcv4ch = ADC1_GetConversionValue();
            ADC1_ClearFlag(ADC1_FLAG_EOC);
            adcindoing = 0;
        }
    }
    else
    {
        ADC1_StartConversion();
        adcindoing = !0;
    }
}
#endif
/*
void adc_monitor2()
{
    if (adcindoing)
    {
        adcstatus = ADC1_GetFlagStatus(ADC1_FLAG_EOC);
        if(adcstatus){
            adcv3ch = ADC1_GetBufferValue(ADC1_CHANNEL_3);
            adcv4ch = ADC1_GetBufferValue(ADC1_CHANNEL_4);
            ADC1_ClearFlag(ADC1_FLAG_EOC);
            adcindoing = 0;
        }
    }
    else
    {
        ADC1_StartConversion();
        adcindoing = !0;
    }
}
*/
uint8_t uart_send_fifo[UART_FIFO_SIZE];
uint8_t uart_sff_ip;
uint8_t uart_sff_op;
uint8_t uart_recv_fifo[UART_FIFO_SIZE];
uint8_t uart_rff_ip;
uint8_t uart_rff_op;
uint8_t soft_send_fifo[SOFT_SEND_FFSZ];
uint8_t soft_sff_ip;
uint8_t soft_sff_op;
/**
  * @brief  Common fifo functions.
  * @param  dat or *dat
  * @param  idx/odx
  * @param  fifoaddr/fifosize
  * @retval fail in full/empty return -1, success return 0.
  */
void fifo_init()
{
    uart_sff_ip = 0;
    uart_sff_op = 0;
    uart_rff_ip = 0;
    uart_rff_op = 0;
    soft_sff_ip = 0;
    soft_sff_op = 0;
}

int8_t fifo_addin(uint8_t dat, uint8_t *idx, uint8_t *odx, uint8_t *fifoaddr, uint8_t fifosize)
{
    if (*odx){
        if (*idx != (*odx-1)){
            fifoaddr[*idx] = dat;
            *idx += 1;
            if (*idx == fifosize){
                *idx = 0;
            }
        }else{
            return -1;
        }
    }else{
        if (*idx != fifosize-1){
            fifoaddr[*idx] = dat;
            *idx += 1;
        }else{
            return -1;
        }
    }
    return 0;
}
            
int8_t fifo_getout(uint8_t *dat, uint8_t *idx, uint8_t *odx, uint8_t *fifoaddr, uint8_t fifosize)
{
    if (*odx != *idx){
        *dat = fifoaddr[*odx];
        *odx += 1;
        if (*odx == fifosize){
            *odx = 0;
        }
    }else{
        return -1;
    }
    return 0;
}

int8_t fifo_peek(uint8_t *dat, uint8_t *idx, uint8_t *odx, uint8_t *fifoaddr)
{
    if (*odx != *idx){
        *dat = fifoaddr[*odx];
    }else{
        return -1;
    }
    return 0;
}

int8_t fifo_delete(uint8_t *idx, uint8_t *odx, uint8_t fifosize)
{
    if (*odx != *idx){
        *odx += 1;
        if (*odx == fifosize){
            *odx = 0;
        }
    }else{
        return -1;
    }
    return 0;
}

//soft timer
uint16_t tmBase;
uint16_t tmBaseLast;
uint16_t tBase;        //basic event recorder
uint8_t tBaseKeyDeb;  //event recorder face to  key debounce

void softimer_init()
{
    tmBase = 0;
    tmBaseLast = 0;
    tBase = 0;
}

//keys
#if 0
uint8_t KeyDeboCnt;
uint8_t sInKeyDeb;
uint8_t keyjust;
uint8_t keylast;
uint8_t KeyChBV;
uint8_t KeyHist;

void key_init()
{
    keylast = getfunckey();  //avoid key holding when power on.
    KeyHist = keylast;
    tBaseKeyDeb = 0;
}

//uint8_t test=0xaa;
//uint8_t md;
void getkeycode()
{
  if(tBaseKeyDeb) //once per 10ms
  {
    tBaseKeyDeb = 0;
    if(sInKeyDeb)
    {
      keyjust = getfunckey();
      if(keyjust != keylast)
      {
        keylast = keyjust;
        KeyDeboCnt = KEY_DEB_REP_TIMES;
      }
      else{
        --KeyDeboCnt;
        if(0 == KeyDeboCnt)
        {
          sInKeyDeb = 0;
          //========================
          //process key start
          KeyChBV = KeyHist ^ keylast;
          if(1 == KeyChBV){
            if(1&KeyHist){
                //key_1 press
                //GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
                //GPIO_WriteReverse(PMA_GPIO_PORT, (GPIO_Pin_TypeDef)PM_BATT_OUT_PINS);
                //GPIO_WriteReverse(PMA_GPIO_PORT, (GPIO_Pin_TypeDef)PM_DCOK_PINS);
/*switch(md)
{
case 0:send2uart_device((uint8_t*)at_autobaudrate, 20);break;
case 1:send2uart_device((uint8_t*)at_cpinq, 10);break;
case 2:send2uart_device((uint8_t*)at_cregQ, 10);break;
case 3:send2uart_device((uint8_t*)at_cgregQ, 11);break;
case 4:send2uart_device((uint8_t*)at_qimode, 13);break;
case 5:send2uart_device((uint8_t*)at_qicsgp, 21);break;
case 6:send2uart_device((uint8_t*)at_qiregapp, 13);break;
case 7:send2uart_device((uint8_t*)at_qicsgpQ, 12);break;
case 8:send2uart_device((uint8_t*)at_qiact, 10);break;
case 9:send2uart_device((uint8_t*)at_qilocip, 12);break;
case 10:send2uart_device((uint8_t*)at_atv1, 6);break;
case 11:send2uart_device((uint8_t*)at_qihead, 13);break;
case 12:send2uart_device((uint8_t*)at_qidnsip, 14);break;
case 13:send2uart_device((uint8_t*)at_qiopen, 40);break;
case 14:send2uart_device((uint8_t*)at_qisend21, 14);break;
case 15:send2uart_device((uint8_t*)mqtt_connect, 21);break;
case 16:send2uart_device((uint8_t*)at_qisend28, 14);break;
case 17:send2uart_device((uint8_t*)mqtt_publish, 28);break;
default:break;
}
++md;
if(18 == md){
    md = 0;
}*/
                //TIM2_SetCounter(15);
                //TIM2_Cmd(ENABLE);
                //GPIO_WriteHigh(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
                //soft_send_byte(test);
                //test++;
                //--------------------------------
                // show 3: NNN
                /*send2uartfifo(0x33);
                send2uartfifo(0x3A);
                send2uartfifo(0x20);
                send2uartfifo((uint8_t)((adcv3ch >> 8)+0x30));
                  
                uint8_t hv = (uint8_t)adcv3ch;
                uint8_t hhv = hv >> 4;
                uint8_t hlv = hv & 0x0F;
                digit2char(&hhv);
                digit2char(&hlv);
                send2uartfifo(hhv);
                send2uartfifo(hlv);
                
                //4bl
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                
                // show 4: NNN
                send2uartfifo(0x34);
                send2uartfifo(0x3A);
                send2uartfifo(0x20);
                send2uartfifo((uint8_t)((adcv4ch >> 8)+0x30));
                  
                hv = (uint8_t)adcv4ch;
                hhv = hv >> 4;
                hlv = hv & 0x0F;
                digit2char(&hhv);
                digit2char(&hlv);
                send2uartfifo(hhv);
                send2uartfifo(hlv);
                
                //CRLF
                send2uartfifo(0x0D);
                send2uartfifo(0x0A);
                UART1_ITConfig(UART1_IT_TXE, ENABLE);
                //--------------------------------*/
            }else{ //ion key release
            }
          }else if(2 == KeyChBV){
            if(2&KeyHist){
                //key_2 press

            }else{ //uv key release
            }
          }else if (4 == KeyChBV){
            if(4&KeyHist){
                //key_3 press

            }else{ //mode key release
            }
          }else{}
          KeyHist = keylast;
          //========================
        }
      }
    }else{
      keyjust = getfunckey();
      if(keyjust != keylast)
      {
        sInKeyDeb = 0xff;
        keylast = keyjust;
        KeyDeboCnt = KEY_DEB_REP_TIMES;
      }
    }
  }
}

uint8_t getfunckey()
{
  uint8_t v;
  v = 0;
  if(GPIO_ReadInputPin(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_GPIO_PINS))
  {
      v |= 0x01;
  }
  /*if(digitalRead(key01_NGO))
  {
    v |= 0x01;
  }
  if(digitalRead(key02_UVR))
  {
    v |= 0x02;
  }
  if(digitalRead(key03_MOD))
  {
    v |= 0x04;
  }*/
  //if(digitalRead(key04_FTM))
  //{
  //  v |= 0x08;
  //}
  return v;
}
#endif
/*
int8_t send2uartfifo(uint8_t data)
{
    int8_t retv;
    retv = fifo_addin(data, &uart_sff_ip, &uart_sff_op, uart_send_fifo, UART_FIFO_SIZE);
    return retv;
}*/

int8_t send2consoleb(uint8_t data)
{
    int8_t retv;
    retv = fifo_addin(data, &soft_sff_ip, &soft_sff_op, soft_send_fifo, SOFT_SEND_FFSZ);
    return retv;
}

int8_t send2console(uint8_t *data, uint8_t N)
{
    int8_t retv;
    uint8_t n=N;
    while(n>0){
        retv = fifo_addin(*data, &soft_sff_ip, &soft_sff_op, soft_send_fifo, SOFT_SEND_FFSZ);
        if(0 == retv)
        {
            --n;
            ++data;
        }
    }
    return n;
}

int8_t send2uart_device(uint8_t *data, uint8_t n)
{
    int8_t retv;
    
    while(n>0){
        retv = fifo_addin(*data, &uart_sff_ip, &uart_sff_op, uart_send_fifo, UART_FIFO_SIZE);
        if(0 == retv)
        {
            --n;
            ++data;
        }else{
            UART1_ITConfig(UART1_IT_TXE, ENABLE);
            waitn(20);
        }
    }
    UART1_ITConfig(UART1_IT_TXE, ENABLE);
    return n;
}
/*
int8_t uart_sendfifo_isempty()
{
    if (uart_sff_ip == uart_sff_op){
        return -1;
    }
    return 0;
}*/

void digit2char(uint8_t* ch)
{
  *ch += 0x30;
  if(*ch > 0x39)
    *ch += 7;
}

extern int8_t getRespState();
extern void tomatch(uint8_t dat);
extern void AsyncCmdMatch(uint8_t dat);

void uart_recv_monitor()
{
    int8_t retv;
    uint8_t data;
    retv = fifo_getout(&data, &uart_rff_ip, &uart_rff_op, uart_recv_fifo, UART_FIFO_SIZE);
    if ( -1 != retv){
        //AsyncCmdMatch(data);
        send2consoleb(data);
        if(getRespState()){
            tomatch(data);
        }
        /*
        switch(data){
        case 1:GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_5);break;
        case 2:GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_3);break;
        case 3:GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_6);break;
        case 4:GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_7);break;
        case 'O':GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_5);break;
        case 'K':GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)GPIO_PIN_3);break;
        default:GPIO_WriteReverse(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
        }*/
    }
}


/*==============================================================================
===============================================================================*/



void soft_send_monitor()
{
    int8_t retv;
    uint8_t data;
    retv = fifo_peek(&data, &soft_sff_ip, &soft_sff_op, soft_send_fifo);
    if ( -1 != retv){
        retv = soft_send_byte(data);
        if ( -1 != retv){
            fifo_delete(&soft_sff_ip, &soft_sff_op, SOFT_SEND_FFSZ);
        }
    }
}
/*==============================================================================
===============================================================================*/
/*
void loopshow()
{
    if (uart_sendfifo_isempty())
    {
                //--------------------------------
                // show 3: NNN
                send2uartfifo(0x33);
                send2uartfifo(0x3A);
                send2uartfifo(0x20);
                send2uartfifo((uint8_t)((adcv3ch >> 8)+0x30));
                  
                uint8_t hv = (uint8_t)adcv3ch;
                uint8_t hhv = hv >> 4;
                uint8_t hlv = hv & 0x0F;
                digit2char(&hhv);
                digit2char(&hlv);
                send2uartfifo(hhv);
                send2uartfifo(hlv);
                
                //4bl
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                send2uartfifo(0x20);
                
                // show 4: NNN
                send2uartfifo(0x34);
                send2uartfifo(0x3A);
                send2uartfifo(0x20);
                send2uartfifo((uint8_t)((adcv4ch >> 8)+0x30));
                  
                hv = (uint8_t)adcv4ch;
                hhv = hv >> 4;
                hlv = hv & 0x0F;
                digit2char(&hhv);
                digit2char(&hlv);
                send2uartfifo(hhv);
                send2uartfifo(hlv);
                
                //CRLF
                send2uartfifo(0x0D);
                send2uartfifo(0x0A);
                UART1_ITConfig(UART1_IT_TXE, ENABLE);
                //--------------------------------
    }
}

void check_charge()
{
    if(GPIO_ReadInputPin(PMB_GPIO_PORT, (GPIO_Pin_TypeDef)PM_CHRG_PINS))
    {
        GPIO_WriteHigh(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
    }else{
        GPIO_WriteLow(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS);
    }
}

uint8_t tLongTimeBase;  //event 256ms
uint8_t pwrkey_delay;

void alarm_callback()
{
    GPIO_WriteHigh(MC20_GPIO_PORT, (GPIO_Pin_TypeDef)MC20_PWRK_PINS);
}

void event_alarm_init()
{
    pwrkey_delay = 0;
}

void event_alarm_set(uint8_t n)
{
    pwrkey_delay = n;
}

void event_alarm_trig()
{
    if(tLongTimeBase){
        tLongTimeBase = 0;
        if(pwrkey_delay){
            --pwrkey_delay;
            if(0 == pwrkey_delay){
                alarm_callback();
            }
        }
    }
}
*/
uint8_t soft_bit_mask;
uint8_t soft_bit_counter;
uint8_t soft_sending;
uint8_t soft_send_data;

int8_t soft_send_byte(uint8_t data)
{
    if(TRUE == soft_sending){
        return -1;
    }
    soft_bit_mask = 1;
    soft_bit_counter = 0;
    soft_sending = TRUE;
    soft_send_data = data;
    GPIO_WriteLow(SOFT_SEND_PORT, (GPIO_Pin_TypeDef)SOFT_SEND_PINS);
    TIM2_SetCounter(BR9600_RELOAD);
    TIM2_Cmd(ENABLE);
    return 0;
}
